
package com.compuvest.web;

/**
 *
 * @author vasil
 */
import java.util.Comparator;

// Collection.sort(you list, new AlphanumComparator())
//

public class AlphanumComparator implements Comparator<String> {

    static final char[] numbers = {'1','2','3','4','5','6','7','8','9','0'};

// <editor-fold defaultstate="collapsed" desc="isIn()">
    private boolean isIn(char ch, char[] chars) {

        for(char symb : chars)
            if(ch == symb) return true;

        return false;
    }
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="inChunk()">
    private boolean inChunk(char ch, String s) {

        if(s.length() == 0) return true;

        char s0 = s.charAt(0);
        int chunkType = 0;	// 0 = alphabetic, 1 = numeric

        if(isIn(s0, numbers)) chunkType = 1;

        if((chunkType == 0) && (isIn(ch, numbers))) return false;
        if((chunkType == 1) && (!isIn(ch, numbers))) return false;

        return true;
    }

// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="compare()">
    public int compare(String o1, String o2) {

        String s1 = o1;
        String s2 = o2;

        int thisMarker = 0;
        int thisNumericChunk = 0;
        String thisChunk = "";

        int thatMarker = 0;
        int thatNumericChunk = 0;
        String thatChunk = "";

        while((thisMarker < s1.length()) && (thatMarker < s2.length())) {

            char thisCh = s1.charAt(thisMarker);
            char thatCh = s2.charAt(thatMarker);

            thisChunk = "";
            thatChunk = "";

            while((thisMarker < s1.length()) && inChunk(thisCh, thisChunk)) {

                thisChunk += thisCh;
                thisMarker++;
                if(thisMarker < s1.length()) thisCh = s1.charAt(thisMarker);
            }

            while((thatMarker < s2.length()) && inChunk(thatCh, thatChunk)) {

                thatChunk += thatCh;
                thatMarker++;
                if(thatMarker < s2.length()) thatCh = s2.charAt(thatMarker);
            }

            int thisChunkType = isIn(thisChunk.charAt(0), numbers) ? 1 : 0;
            int thatChunkType = isIn(thatChunk.charAt(0), numbers) ? 1 : 0;

            // if both chanks contain numeric characters, sort them numerically
            int result = 0;

            if((thisChunkType == 1) && (thatChunkType == 1)) {
                try {
                    thisNumericChunk = Integer.parseInt(thisChunk);
                    thatNumericChunk = Integer.parseInt(thatChunk);
                }
                catch(NumberFormatException ignore) { }

                if(thisNumericChunk < thatNumericChunk) result = -1;
                if(thisNumericChunk > thatNumericChunk) result = 1;
            }
            else {
                result = thisChunk.compareTo(thatChunk);
            }

            if(result != 0) return result;

        } // while

        return 0;
    }
// </editor-fold>

}
